package utils;


import beans.HttpConfig;
import dao.SocketLogDao;

import javax.servlet.http.HttpServlet;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 本类是针对socket通信建立的日志存储功能的
 * 其中主要部分是对于socket文件读取并存储，需要将gbk编码的日志文件转化为utf-8编码的文件进行存储
 * 其中，socket传过来的文件名并不是gbk格式的，是utf-8编码格式的
 */
public class SocketLog extends HttpServlet {
    private static final long serialVersionUID = 5153949596750818310L;
    private ServerSocket  serverSocket ;
	private SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
	private String socketLogFileUri = HttpConfig.socketLogFileUri;
	private String socketLogLevel = HttpConfig.socketLogLevel;
	private SocketLogDao socketLogDao = new SocketLogDao();
	private int index = 0;
	public static void main(String[] args) {
		new SocketLog();
	}

	public SocketLog() {
		try{
			serverSocket = new ServerSocket(50030);
		}catch(IOException e){
			e.printStackTrace();
			return;
		}
		//创建新的监听主线程，这个线程创建ServerSocket监听
		new Thread(new Runnable(){
			public void run(){

				while(true){
					Socket socket = null;
					try{
						Log4jInit.logger.info("The server starts monitoring, port number:50030");
						socket = serverSocket.accept();
						index++;
						//当监听到了客户端连接后，创建新线程传输数据，这样可以实现多个客户端同时访问
						new SocketHandleThread(socket).start();
					}catch(Exception e){
						Log4jInit.logger.info("The server started monitoring failed, port number:50030");
					}
				}
			}
		}).start();
	}

	class SocketHandleThread extends Thread{
		Socket socket;
		DataOutputStream out;
		DataInputStream in;
		int selfIndex = index;

		SocketHandleThread(Socket t){
			Log4jInit.logger.info("Accept the connection from the client socket and start the thread to handle the connection");
			socket = t;
			try{
				in = new DataInputStream(socket.getInputStream());
				out = new DataOutputStream(socket.getOutputStream());
			}catch(IOException e){
				e.printStackTrace();
			}

		}
		public void run()
		{
			while(true){
				try{

					if(in.available()>0){

                        byte b = in.readByte();
                        Log4jInit.logger.info(">>>>begin receive>>>>>>>");
                        switch(b) {
                            case 'F':{
                                Log4jInit.logger.info(">>>>"+selfIndex+"收到客户端发送日志文件操作");

                                int nLen = in.readInt();
                                byte[] bId = new byte[nLen];
                                in.read(bId,0,nLen);
                                String id = new String(bId, "ISO-8859-1");

                                nLen = in.readInt();
                                byte[] bPsn = new byte[nLen];
                                in.read(bPsn,0,nLen);
                                String psn = new String(bPsn, "ISO-8859-1");


                                nLen = in.readInt();
                                byte[] bName = new byte[nLen];
                                in.read(bName,0,nLen);
                                //解析文件名称，其为utf-8的编码格式
                                String logName = new String(bName, "gbk");
                                logName = new String(logName.getBytes("UTF-8"));
                                String socketLogFilePath = socketLogFileUri+sf.format(new Date())+"-"+logName;
                                FileOutputStream fsOut = new FileOutputStream(socketLogFilePath);

                                long mLen = in.readLong();
                                Log4jInit.logger.info(">>>>"+selfIndex+"日志文件长度："+mLen);

                                Log4jInit.logger.info(">>>>"+selfIndex+"算法id="+id+"，psn="+psn+"，日志文件名："+logName+"，长度为"+nLen);

                                byte[] bArray;
                                if(mLen>4096) {
                                    bArray= new byte[4096];
                                }else {
                                    bArray= new byte[(int) mLen];
                                }

                                long remainLen=mLen;
                                //将文件内容进行从gbk到utf-8的编码格式转化
                                while(remainLen>0) {
                                    if(remainLen>4096) {
                                        in.read(bArray,0,4096);
                                //        String temp = new String(bArray,"gbk");
                               //         fsOut.write(temp.getBytes("UTF-8"));
                                        fsOut.write(bArray);;
                                        remainLen -=4096;
                                    }
                                    else {
                                        in.read(bArray,0,(int) remainLen);
                                        String temp = new String(bArray,"gbk");
                                        fsOut.write(bArray,0,(int) remainLen); 
                                		remainLen -=remainLen;
                        //                fsOut.write(temp.getBytes("utf-8"));
                               //         remainLen -=remainLen;
                                    }
                                }

                                fsOut.close();
                                Log4jInit.logger.info(">>>>"+selfIndex+"接收日志文件完毕，发送返回值");
                                //发送返回信息
                                out.write("F1".getBytes(), 0, 2);
                                socketLogDao.insertLogFileUri(socketLogLevel, socketLogFilePath, psn, id);
                                break;
                            }
                            case 'M':{
                                Log4jInit.logger.info(">>>>"+selfIndex+"收到客户端发送消息操作");
                                FileOutputStream fsOut = new FileOutputStream("jcptMessage.log",true);

                                int nLen = in.readInt();
                                byte[] bId = new byte[nLen];
                                in.read(bId,0,nLen);
                                String id = new String(bId, "ISO-8859-1");

                                nLen = in.readInt();
                                byte[] bPsn = new byte[nLen];
                                in.read(bPsn,0,nLen);
                                String psn = new String(bPsn, "ISO-8859-1");

                                int mLen = in.readInt();
                                Log4jInit.logger.info("消息长度:"+mLen);
                                byte[] bArray = new byte[mLen];
                                in.read(bArray,0,mLen);
                                fsOut.write(bArray);
                                fsOut.close();
                                String message = new String(bArray, "GBK");
                                Log4jInit.logger.info(">>>>"+selfIndex+"收到来自客户端的消息：id="+id+",psn="+psn+",消息："+message);
                                //发送返回信息
                                out.write("M1".getBytes(), 0, 2);
                                socketLogDao.insertLogMessage(socketLogLevel,message,psn,id);
                                break;
                            }case 'S':{
                                //2018-7-12记录一下，这里status的值只可能是1或者0，1：算法运行成功；0：算法运行失败
                                Log4jInit.logger.info(">>>>"+selfIndex+"收到客户端发送的算法执行状态信息");
                                int nLen = in.readInt();
                                byte[] bId = new byte[nLen];
                                in.read(bId,0,nLen);
                                String id = new String(bId, "ISO-8859-1");

                                nLen = in.readInt();
                                byte[] bPsn = new byte[nLen];
                                in.read(bPsn,0,nLen);
                                String psn = new String(bPsn, "ISO-8859-1");

                                //这里需要保证status的值必须为0或者1
                                int status = in.readInt();
                                Log4jInit.logger.info(">>>>"+selfIndex+"算法:id="+id+",psn="+psn+",执行状态为："+status);
                                //发送返回信息
                                out.write("S1".getBytes(), 0, 2);
                                socketLogDao.insertAlgorithmState(socketLogLevel,status+"",psn,id,null);
                                break;
                            }case 'P':{
                                Log4jInit.logger.info(">>>>"+selfIndex+"收到客户端发送的算法执行进度信息");
                                int nLen = in.readInt();
                                byte[] bId = new byte[nLen];
                                in.read(bId,0,nLen);
                                String id = new String(bId, "ISO-8859-1");

                                nLen = in.readInt();
                                byte[] bPsn = new byte[nLen];
                                in.read(bPsn,0,nLen);
                                String psn = new String(bPsn, "ISO-8859-1");

                                int process = in.readInt();
                                Log4jInit.logger.info(">>>>"+selfIndex+"算法:id="+id+",psn="+psn+"，执行进度为："+process);
                                //发送返回信息
                                out.write("P1".getBytes(), 0, 2);
                                socketLogDao.insertAlgorithmSchedule(socketLogLevel,process+"",psn,id);
                                break;
                            }
                            default:
                                Log4jInit.logger.info("wrong operate code");
                        }
                    }
				}

				catch (IOException e){
                	e.printStackTrace();
					Log4jInit.logger.info("client leave");
					return;
				}
			}
		}
	}

}